package com.qiche.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qiche.aspect.Result;
import com.qiche.constant.AccountType;
import com.qiche.constant.PayStatus;
import com.qiche.dto.*;
import com.qiche.enums.ResultEnum;
import com.qiche.enums.SubscribeStatusEnum;
import com.qiche.mapper.StoreMemberMapper;
import com.qiche.mapper.SubscribeMapper;
import com.qiche.mapper.SubscribeProductMapper;
import com.qiche.model.*;
import com.qiche.requestpram.SubscribeParam;
import com.qiche.service.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 预约操作 service
 *
 * @author chendezhi
 * @date 2018/3/1 17:45
 */
@Service
public class SubscribeServiceImpl extends BaseService<Subscribe> implements SubscribeService {

	@Autowired
	private SubscribeMapper subscribeMapper;

	@Autowired
	private ProductService productService;

	@Autowired
	private SubscribeProductService subscribeProductService;
	@Autowired
	private SubscribeProductMapper subscribeProductMapper;
	@Autowired
	private ProductCategoryService productCategoryService;
	@Autowired
	private MerchantService merchantService;

	@Autowired
	private ServiceItemWorkstageService itemWorkstageService;
	@Autowired
	private StoreMemberCarService storeMemberCarService;

	@Autowired
	private StoreMemberMapper storeMemberMapper;

	@Override
	public List<Subscribe> getServiceListByCustomerId(Long customerId) {
		Example example = new Example(Subscribe.class);
		Example.Criteria criteria = example.createCriteria();
		criteria.andEqualTo("customerId", customerId);
		// criteria.andIn("subscribeStatus",Arrays.asList(SubscribeStatusEnum.SUBSCRIBING.getStatus(),SubscribeStatusEnum.CANCEL.getStatus()));
		criteria.andIn("subscribeStatus", Arrays.asList(1, 2));
		// criteria.andNotEqualTo("subscribeStatus",SubscribeStatusEnum.SUBSCRIBING);
		List<Subscribe> subscribeList = selectByExample(example);
		return subscribeList;
	}

	/**
	 * 拷贝 属性 Product -> SubscribeProductDto
	 *
	 * @param product
	 * @return
	 */
	public static SubscribeProductDto createSubscribeProductDto(Product product) {
		SubscribeProductDto subscribeProductDto = new SubscribeProductDto();
		BeanUtils.copyProperties(product, subscribeProductDto);
		return subscribeProductDto;
	}

	@Override
	public SubscribeDto toSubscribe(StoreMember storeMember, Long memberCarId, Long merchantId) {

		// 获取 会员信息,及会员对应的车辆信息
		String carInfo = "";
		String plateNumber = "";
		Long memCarId = null;
		if (storeMember != null) {
			if (memberCarId == null) {
				Example memberCarExa = new Example(StoreMemberCar.class);
				Example.Criteria criteria = memberCarExa.createCriteria();
				criteria.andEqualTo("storeMemberId", storeMember.getId());
				memberCarExa.setOrderByClause("update_time desc");
				List<StoreMemberCar> memberCars = storeMemberCarService.selectByExample(memberCarExa);
				if (memberCars.size() != 0) {
					StoreMemberCar memberCar = memberCars.get(0);
					carInfo = memberCar.getCarInfo();
					plateNumber = memberCar.getPlateNumber();
					memCarId = memberCar.getId();
				}
			} else {
				StoreMemberCar memberCar = storeMemberCarService.selectByKey(memberCarId);
				carInfo = memberCar.getCarInfo();
				plateNumber = memberCar.getPlateNumber();
				memCarId = memberCar.getId();
			}
		}

		SubscribeDto subscribeDto = new SubscribeDto();

		/* ------------------- 遍历 且拼接出 前端展示 服务结构 -------------------------- */
		List<ProductCategoryDto> productCategoryDtos = productCategoryService
				.selectProductCategoryByMerchantId(merchantId);
		subscribeDto.setProductCategoryDtos(productCategoryDtos);

		/* ------------------- 会员前端展示结构 -------------------------- */
		if (storeMember != null) {
			SubscribeMember subscribeMember = new SubscribeMember();
			BeanUtils.copyProperties(storeMember, subscribeMember);
			subscribeMember.setCarInfo(carInfo);
			subscribeMember.setCarNum(plateNumber);
			subscribeMember.setMemberCarId(memCarId);
			subscribeDto.setSubscribeMember(subscribeMember);
		}
		return subscribeDto;
	}

	@Override
	public MemberSubscribeDetailDto memberSubscribeDetail(Subscribe subscribe) {
		if (subscribe != null) {
			// 获取用户信息
			Long customerId = subscribe.getCustomerId();
			StoreMember storeMember = storeMemberMapper.selectByPrimaryKey(customerId);

			// 获取预约信息
			return getMemberSubscribeDetailDtoBySubscribe(subscribe, storeMember);
		}
		return null;
	}

	/**
	 * 通过 预约订单 获取简约 预约项展示
	 *
	 * @param subscribe
	 * @param storeMember
	 * @return
	 */
	private MemberSubscribeDetailDto getMemberSubscribeDetailDtoBySubscribe(Subscribe subscribe,
			StoreMember storeMember) {
		List<Product> products = subscribeProductService.selectProductBySubscribeId(subscribe.getSubscribeId());
		Merchant merchant = merchantService.selectById(subscribe.getMerchantId());
		String productNames = null ;
		for(Product p :products){
			productNames= p.getCategoryName()+"："+p.getName();
		}
		Double sumPrice = products.stream().map(Product::getPrice).reduce(0.00, Double::sum);
		MemberSubscribeDetailDto memberSubscribeDetailDto = new MemberSubscribeDetailDto();
		BeanUtils.copyProperties(subscribe, memberSubscribeDetailDto);
		memberSubscribeDetailDto.setPhone(storeMember.getPhone());
		memberSubscribeDetailDto.setUsername(storeMember.getName());
		memberSubscribeDetailDto.setMerchantName(merchant.getName());

		StoreMember storeMember1 = storeMemberMapper.selectByPrimaryKey(subscribe.getCustomerId());
		if (storeMember != null) {
			memberSubscribeDetailDto.setStoreMemberId(storeMember1.getId());
		}

		memberSubscribeDetailDto.setProducts(productNames);
		memberSubscribeDetailDto.setPrice(sumPrice);
		memberSubscribeDetailDto.setMerchantImg(merchant.getMerchantImg());
		return memberSubscribeDetailDto;
	}

	@Override
	public List<MemberSubscribeDetailDto> selectAllMemberSubscribe(StoreMember member,String status) {
		Example subExam = new Example(Subscribe.class);
		Example.Criteria criteria = subExam.createCriteria();
		criteria.andEqualTo("customerId", member.getId());
		  List<String> result = Arrays.asList(status.split(","));
	        if (status!=null&&result.size()==1){
	            criteria.andEqualTo("subscribeStatus", status);
	        }else{
	        criteria.andIn("subscribeStatus", result);	
	        }
		subExam.setOrderByClause("create_time DESC");
		List<Subscribe> subscribes = this.selectByExample(subExam);

		List<MemberSubscribeDetailDto> memberSubscribeDetailDtos = subscribes.stream()
				.map(subscribe -> getMemberSubscribeDetailDtoBySubscribe(subscribe, member))
				.collect(Collectors.toList());
		return memberSubscribeDetailDtos;
	}

	/**
	 * 提交预约
	 * 
	 * @param subscribe
	 * @param memberCarId
	 * @param productIds
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class)
	@Override
	public Result subscribe(Subscribe subscribe, Long memberCarId, List<Long> productIds) {
		// 新增预约记录
		subscribe.setPayStatus(PayStatus.PAY_NON);
		int save = subscribeMapper.insert(subscribe);

		List<SubscribeProduct> subscribeProducts = productIds.stream()
				.map(productId -> new SubscribeProduct(subscribe.getSubscribeId(), productId))
				.collect(Collectors.toList());

		// 插入服务项目
		subscribeProductMapper.insertList(subscribeProducts);
		/*
		 * for (SubscribeProduct subscribeProduct: subscribeProducts) { //插入服务项目
		 * subscribeProductMapper.insert(subscribeProduct); //生成服务项目实时工序记录
		 * itemWorkstageService.generateWorkstageBySubproId(subscribeProduct.
		 * getSubProId()); }
		 */
		return Result.createBySuccess("预约成功");
	}

	/**
	 * 门店保存预约
	 * 
	 * @param subscribe
	 * @param productIds
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class)
	@Override
	public Result userSubscribe(Subscribe subscribe, List<Long> productIds) {

		int save = subscribeMapper.insert(subscribe);

		List<SubscribeProduct> subscribeProducts = productIds.stream()
				.map(productId -> new SubscribeProduct(subscribe.getSubscribeId(), productId))
				.collect(Collectors.toList());
		int i = subscribeProductService.insertBatch(subscribeProducts);

		return Result.createBySuccess(subscribe);
	}

	/**
	 * 门店更新预约
	 * 
	 * @param subscribe
	 * @param productIds
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class)
	@Override
	public int userSubscribeUpdate(Subscribe subscribe, List<Long> productIds) {
		int update = subscribeMapper.updateByPrimaryKeySelective(subscribe);

		// int save = subscribeMapper.insert(subscribe);
		if (update > 0) {
			// 找到该预约之前的服务产品关联
			int deletCount = subscribeProductService.deleteBySubscribeId(subscribe.getSubscribeId());
			List<SubscribeProduct> subscribeProducts = productIds.stream()
					.map(productId -> new SubscribeProduct(subscribe.getSubscribeId(), productId))
					.collect(Collectors.toList());
			int i = subscribeProductService.insertBatch(subscribeProducts);
			if (i > 0) {
				return i;
			}
		}
		return 0;
	}

	@Override
	public UserSubscribeDto userSubscribeByStatus(User user, Byte subscribeStatus, Integer pageNo, Integer pageSize) {
		Example example = new Example(Subscribe.class);
		example.setOrderByClause("create_time DESC");
		Example.Criteria criteria = example.createCriteria();
		criteria.andEqualTo("merchantId", user.getMerchantId());
		if (subscribeStatus != null) {
			criteria.andEqualTo("subscribeStatus", subscribeStatus);
		}

		PageHelper.startPage(pageNo, pageSize);
		List<Subscribe> allSubscribes = selectByExample(example);
		PageInfo<Subscribe> subscribePageInfo = new PageInfo<>(allSubscribes);
		List<Subscribe> subscribes = subscribePageInfo.getList();
		List<MemberSubscribeDetailDto> collect = subscribes.stream().map(this::memberSubscribeDetail)
				.collect(Collectors.toList());
		UserSubscribeDto userSubscribeDto = new UserSubscribeDto();
		userSubscribeDto.setSubscribeDetailDtos(collect);
		BeanUtils.copyProperties(subscribePageInfo, userSubscribeDto);
		return userSubscribeDto;
	}

	@Override
	public UserSubscribeDto userAllSubscribe(User user, Integer pageNo, Integer pageSize, Integer status) {
		Example example = new Example(Subscribe.class);
		example.setOrderByClause("create_time DESC");
		Example.Criteria criteria = example.createCriteria();
		criteria.andEqualTo("merchantId", user.getMerchantId());
		// 预约 不包含 结算的
		if (status == SubscribeStatusEnum.CLOSE_SUBSCRIBE.getStatus().intValue()) {
			// 查询所有
			criteria.andNotEqualTo("subscribeStatus", SubscribeStatusEnum.CLOSE_SUBSCRIBE.getStatus());
		} else {
			criteria.andEqualTo("subscribeStatus", status);
		}
		PageHelper.startPage(pageNo, pageSize);
		List<Subscribe> allSubscribes = selectByExample(example);
		PageInfo<Subscribe> subscribePageInfo = new PageInfo<>(allSubscribes);
		List<Subscribe> subscribes = subscribePageInfo.getList();
		List<MemberSubscribeDetailDto> collect = subscribes.stream().map(this::memberSubscribeDetail)
				.collect(Collectors.toList());
		UserSubscribeDto userSubscribeDto = new UserSubscribeDto();
		userSubscribeDto.setSubscribeDetailDtos(collect);
		BeanUtils.copyProperties(subscribePageInfo, userSubscribeDto);
		return userSubscribeDto;
	}

	@Override
	public UserSubscribeDto userAllService(User user, Integer pageNo, Integer pageSize, Integer status) {
		Example example = new Example(Subscribe.class);
		example.setOrderByClause("create_time DESC");
		Example.Criteria criteria = example.createCriteria();
		criteria.andEqualTo("merchantId", user.getMerchantId());
		// 服务 不包含 预约的
		if (status == SubscribeStatusEnum.SUBSCRIBING.getStatus().intValue()) {
			criteria.andNotEqualTo("subscribeStatus", SubscribeStatusEnum.SUBSCRIBING.getStatus());
		} else {
			criteria.andEqualTo("subscribeStatus", status);
		}
		PageHelper.startPage(pageNo, pageSize);
		List<Subscribe> allSubscribes = selectByExample(example);
		PageInfo<Subscribe> subscribePageInfo = new PageInfo<>(allSubscribes);
		List<Subscribe> subscribes = subscribePageInfo.getList();
		List<MemberSubscribeDetailDto> collect = subscribes.stream().map(this::memberSubscribeDetail)
				.collect(Collectors.toList());
		UserSubscribeDto userSubscribeDto = new UserSubscribeDto();
		userSubscribeDto.setSubscribeDetailDtos(collect);
		BeanUtils.copyProperties(subscribePageInfo, userSubscribeDto);
		return userSubscribeDto;
	}

	private PCUserSubscribeDto subscribeByParam(User user, SubscribeParam subscribeParam, Byte notStatus) {
		if (AccountType.ADMIN != user.getAccountType()) {
			subscribeParam.setMerchantId(user.getMerchantId().longValue());
		}

		subscribeParam.setTypeStatus(notStatus);
		Integer total = subscribeMapper.countSubscribeByParam(subscribeParam);

		subscribeParam.setTotal(total);
		List<Subscribe> subscribes = subscribeMapper.userSubscribeByParam(subscribeParam);
		List<MemberSubscribeDetailDto> collect = subscribes.stream().map(this::memberSubscribeDetail)
				.collect(Collectors.toList());
		PCUserSubscribeDto userSubscribeDto = new PCUserSubscribeDto();
		userSubscribeDto.setSubscribeDetailDtos(collect);
		userSubscribeDto.setSubscribeParam(subscribeParam);
		return userSubscribeDto;
	}

	@Override
	public PCUserSubscribeDto userSubscribeByParam(User user, SubscribeParam subscribeParam) {
		return subscribeByParam(user, subscribeParam, SubscribeStatusEnum.CLOSE_SUBSCRIBE.getStatus());
	}

	@Override
	public PCUserSubscribeDto userServiceByParam(User user, SubscribeParam subscribeParam) {
		return subscribeByParam(user, subscribeParam, SubscribeStatusEnum.SUBSCRIBING.getStatus());
	}

	@Override
	public List<Subscribe> selectAllColseByMerchantId(Integer merchantId) {
		Example example = new Example(Subscribe.class);
		Example.Criteria criteria = example.createCriteria();
		criteria.andEqualTo("merchantId", merchantId);
		criteria.andEqualTo("subscribeStatus", SubscribeStatusEnum.CLOSE_SUBSCRIBE.getStatus());
		return subscribeMapper.selectByExample(example);
	}

	@Override
	public Integer selectCountByMerchantIdSubscribeTimeStatus(Integer merchantId,String subscribeTime) {
		Example example = new Example(Subscribe.class);
		Example.Criteria criteria = example.createCriteria();
		criteria.andEqualTo("merchantId", merchantId);
		criteria.andEqualTo("subscribeTime", subscribeTime);
		criteria.andEqualTo("subscribeStatus", 0);
		return subscribeMapper.selectCountByExample(example);
	}
	
	@Override
    public List<MemberSubscribeDetailDto> selectSubscribeBysToreMemberAndStatus(StoreMember member, String status) {
        Example subExam = new Example(Subscribe.class);
        Example.Criteria criteria = subExam.createCriteria();
        criteria.andEqualTo("customerId", member.getId());
        List<String> result = Arrays.asList(status.split(","));
        if (status!=null&&result.size()==1){
            criteria.andEqualTo("subscribeStatus", status);
        }else{
        criteria.andIn("subscribeStatus", result);	
        }
        subExam.setOrderByClause("create_time DESC");
        List<Subscribe> subscribes = this.selectByExample(subExam);

        List<MemberSubscribeDetailDto> memberSubscribeDetailDtos = subscribes.stream()
                .map(subscribe -> getMemberSubscribeDetailDtoBySubscribe(subscribe, member))
                .collect(Collectors.toList());
        return memberSubscribeDetailDtos;
    }

	/**
	 * 查询用户的预约详情
	 * 
	 * @param subscribe
	 * @return
	 */
	@Override
	public UserSubscribeDetaiDto userSubscribeDetail(Subscribe subscribe) {
		if (subscribe != null) {
			// 获取用户信息
			Long customerId = subscribe.getCustomerId();
			StoreMember storeMember = storeMemberMapper.selectByPrimaryKey(customerId);
			// 获取预约服务信息
			List<Product> products = subscribeProductService.selectProductBySubscribeId(subscribe.getSubscribeId());
			List<SubscribeProductDto> collect = products.stream().map(SubscribeServiceImpl::createSubscribeProductDto)
					.collect(Collectors.toList());

			Double sumPrice = products.stream().map(Product::getPrice).reduce(0.00, Double::sum);

			UserSubscribeDetaiDto userSubscribeDetaiDto = new UserSubscribeDetaiDto();

			userSubscribeDetaiDto.setSubscribeProductDtos(collect);
			userSubscribeDetaiDto.setTotalPrice(sumPrice);
			userSubscribeDetaiDto.setUsername(storeMember.getName());
			userSubscribeDetaiDto.setPhone(storeMember.getPhone());
			userSubscribeDetaiDto.setSubscribeId(subscribe.getSubscribeId());
			userSubscribeDetaiDto.setCarNum(subscribe.getCarNum());
			userSubscribeDetaiDto.setFrameNum(subscribe.getFrameNum());
			userSubscribeDetaiDto.setMemberCarInfo(subscribe.getCustomerCarDesc());
			/*
			 * if (storeMember==null){
			 * userSubscribeDetaiDto.setStoreMemberId(storeMember.
			 * getStoreMemberId()); }
			 */
			return userSubscribeDetaiDto;
		}
		return null;
	}

	@Override
	public Result updateSubscribeStatus(Long subscribeId, Byte status) {
		Subscribe subscribe = subscribeMapper.selectByPrimaryKey(subscribeId);

		if (subscribe == null) {
			return Result.createByResultEnum(ResultEnum.SUBSCRIBE_NOT_EXIST_ERROR);
		}

		Byte subscribeStatus = subscribe.getSubscribeStatus();

		if (SubscribeStatusEnum.OPEN_SUBSCRIBE.getStatus().equals(status)) {
			// 开单
			if (!SubscribeStatusEnum.SUBSCRIBING.getStatus().equals(subscribeStatus)) {
				return Result.createByResultEnum(ResultEnum.NOT_SUBSCRIBING_ERROR);
			}
			subscribe.setSubscribeStatus(SubscribeStatusEnum.OPEN_SUBSCRIBE.getStatus());
		} else if (SubscribeStatusEnum.CANCEL.getStatus().equals(status)) {
			// 取消
			if (SubscribeStatusEnum.CLOSE_SUBSCRIBE.getStatus().equals(subscribeStatus)
					&& SubscribeStatusEnum.CANCEL.getStatus().equals(subscribeStatus)) {
				return Result.createByResultEnum(ResultEnum.NOT_CANCEL_ERROR);
			}
			subscribe.setSubscribeStatus(SubscribeStatusEnum.CANCEL.getStatus());
		} else if (SubscribeStatusEnum.CLOSE_SUBSCRIBE.getStatus().equals(status)) {
			// 结算
			if (!SubscribeStatusEnum.OPEN_SUBSCRIBE.getStatus().equals(subscribeStatus)) {
				return Result.createByResultEnum(ResultEnum.NOT_FINISH_ERROR);
			}
			// 如果是结算，更新结算时间字段
			subscribe.setBalanceTime(new Date());
			// 结算的同时 将所有服务费用算出,存入数据库
			List<Product> products = subscribeProductService.selectProductBySubscribeId(subscribe.getSubscribeId());
			Double sumPrice = products.stream().map(Product::getPrice).reduce(0.00, Double::sum);
			subscribe.setProducesMoney(sumPrice);
			subscribe.setSubscribeStatus(SubscribeStatusEnum.CLOSE_SUBSCRIBE.getStatus());
			// 更新支付状态为 线下支付
			subscribe.setPayStatus(PayStatus.PAY_OFFLINE);
			// 更新用户的消费次数和消费总额
			StoreMember storeMember = storeMemberMapper.selectByPrimaryKey(subscribe.getCustomerId());
			storeMember.setConsumeCount(storeMember.getConsumeCount() + 1);
			storeMember.setConsumeMoney(storeMember.getConsumeMoney().add(new BigDecimal(sumPrice)));
			storeMemberMapper.updateByPrimaryKeySelective(storeMember);

		} else {
			return Result.createByResultEnum(ResultEnum.SUBSCRIBESTATUS_ERROR);
		}

		try {
			int i = subscribeMapper.updateByPrimaryKeySelective(subscribe);
			if (i > 0) {
				// 更新成功
				return Result.createByResultEnum(ResultEnum.SUCCESS);
			} else {
				// 更新失败
				return Result.createByResultEnum(ResultEnum.FAILURE);
			}
		} catch (Exception e) {
			e.printStackTrace();
			return Result.createByResultEnum(ResultEnum.UNKONW_ERROR);
		}
	}

	@Override
	public List<SimpleSubscribeDto> selectSimpleSubscribeDtoByMember(StoreMember storeMember) {
		Example example = new Example(Subscribe.class);
		example.setOrderByClause("create_time DESC");
		Example.Criteria criteria = example.createCriteria();
		criteria.andEqualTo("customerId", storeMember.getId());
		List<Subscribe> subscribes = subscribeMapper.selectByExample(example);
		return subscribes.stream().map(subscribe -> this.getSimpleSubscribeDtoBySubscribe(subscribe, storeMember))
				.collect(Collectors.toList());
	}

	private SimpleSubscribeDto getSimpleSubscribeDtoBySubscribe(Subscribe subscribe, StoreMember storeMember) {
		List<Product> products = subscribeProductService.selectProductBySubscribeId(subscribe.getSubscribeId());
		String productNames = products.stream().map(Product::getName).reduce("",
				(sum, item) -> "".equals(sum) ? sum + item : sum + " + " + item);
		Double sumPrice = products.stream().map(Product::getPrice).reduce(0.00, Double::sum);
		SimpleSubscribeDto simpleSubscribeDto = new SimpleSubscribeDto();
		BeanUtils.copyProperties(subscribe, simpleSubscribeDto);
		simpleSubscribeDto.setProducts(productNames);
		simpleSubscribeDto.setPrice(sumPrice);
		return simpleSubscribeDto;
	}

}
